package com.expert.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.expert.Mapper.ExpertMapper;
import com.expert.constant.MessageConstant;
import com.expert.context.BaseContext;
import com.expert.dto.UserDTO;
import com.expert.enums.ProjectStatus;
import com.expert.exception.AddException;
import com.expert.exception.DeleteException;
import com.expert.exception.UpdateException;
import com.expert.pojo.*;
import com.expert.service.*;
import com.expert.vo.ExpertInfoVo;
import com.expert.vo.ExpertPageVo;
import com.expert.vo.RemoteExpertVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Base64;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName: ExpertServiceImpl
 * @Author: cxs
 * @Date: 2024/03/14 13:08
 * @Description:
 **/
@Service
public class ExpertServiceImpl extends ServiceImpl<ExpertMapper,Expert> implements ExpertService {
    @Autowired
    UserService userService;

    @Autowired
    CategoryService categoryService;
    @Autowired
    NoticeUserService noticeUserService;

    @Value("${expert.expertPhoto.path}")
    String localPhotoPath;

    @Autowired
    ExtractResultService extractResultService;

    @Autowired
    ProjectService projectService;
    /**
     * 添加专家信息
     *
     * @param expert
     */
    @Override
    @Transactional
    public void addExpertService(Expert expert) {

        Long idNumberCount = this.lambdaQuery().eq(Expert::getExpertIdNumber, expert.getExpertIdNumber()).count();
        if (idNumberCount>0){
            throw  new AddException(MessageConstant.EXPERT_ID_NUMBER_REPEAT);
        }
        //查询专家信息是否已经存在
        Long count = this.lambdaQuery().eq(Expert::getExpertName, expert.getExpertName()).eq(Expert::getExpertIdNumber, expert.getExpertIdNumber()).count();
        if (count>0){
            throw  new AddException(MessageConstant.EXPERT_INFORMATION_REPEAT);
        }
       expert.setExpertUser(expert.getExpertUser());
        //创建用户
        UserDTO userDTO=UserDTO.builder()
                .account(expert.getExpertPhone())
                .name(expert.getExpertName())
                .role(3L)
                .sex(expert.getExpertSex())
                .phone(expert.getExpertPhone())
                .idNumber(expert.getExpertIdNumber())
                .isBind(1)
                .build();
        Long userId=this.userService.addUser(userDTO);
        expert.setExpertUser(userId);
        expert.setCreateUser(BaseContext.getCurrentId());
        expert.setUpdateUser(BaseContext.getCurrentId());
        expert.setCreateTime(LocalDateTime.now());
        expert.setUpdateTime(LocalDateTime.now());
        //校验完成，添加信息
        this.save(expert);
    }

    /**
     * 分页查询专家信息
     *
     * @param page
     * @param pageSize
     * @param expertName
     * @param expertSex
     * @param expertTitle
     * @param expertEducation
     * @param expertUnit
     * @param expertCategory
     * @return
     */
    @Override
    public Page<ExpertPageVo> pageExpertService(Integer page, Integer pageSize,
                                                String expertName, Integer expertSex,
                                                String expertTitle, String expertEducation,
                                                String expertUnit, Long expertCategory) {

        Page<Expert> expertPage=new Page<>(page,pageSize);
        page(expertPage,new LambdaQueryWrapper<Expert>()
                .eq(expertCategory!=null,Expert::getExpertCategory,expertCategory)
                .eq(expertSex!=null,Expert::getExpertSex,expertSex)
                .like(StringUtils.isNotEmpty(expertName),Expert::getExpertName,expertName)
                .like(StringUtils.isNotEmpty(expertTitle),Expert::getExpertTitle,expertTitle)
                .like(StringUtils.isNotEmpty(expertEducation),Expert::getExpertEducation,expertEducation)
                .like(StringUtils.isNotEmpty(expertUnit),Expert::getExpertUnit,expertUnit));
        List<Expert> expertList = expertPage.getRecords();
        Page<ExpertPageVo> pageVoPage=new Page<>();
        BeanUtils.copyProperties(expertPage,pageVoPage);
        List<ExpertPageVo> expertPageVoList = expertList.stream().map(expert -> {
            ExpertPageVo expertPageVo = new ExpertPageVo();
            Category category = this.categoryService.selectById(expert.getExpertCategory());
            BeanUtils.copyProperties(expert, expertPageVo);
            expertPageVo.setExpertCategoryName(category.getCategoryCode() + " " + category.getCategoryName());
            return expertPageVo;
        }).toList();
        pageVoPage.setRecords(expertPageVoList);
        return pageVoPage;
    }

    /**
     * 根据id获取专家信息
     *
     * @param id 专家id
     * @return
     */
    @Override
    public ExpertInfoVo getInfoById(Long id) {

        Expert expert = this.lambdaQuery().eq(Expert::getId, id).one();
        if (expert==null){
            return null;
        }
        Category category = this.categoryService.selectById(expert.getExpertCategory());
        ExpertInfoVo expertInfoVo=new ExpertInfoVo();
        BeanUtils.copyProperties(expert,expertInfoVo);

        expertInfoVo.setExpertCategoryName(category.getCategoryCode()+" "+category.getCategoryName());
        String expertPhoto = expert.getExpertPhoto();
        String path=localPhotoPath+expertPhoto;
        FileInputStream inputStream = null;
        String base64Str = "";
        try {
            Base64.Encoder encoder = Base64.getEncoder();
            inputStream = new FileInputStream(path);
            int available = inputStream.available();
            byte[] bytes = new byte[available];
            inputStream.read(bytes);
            base64Str = encoder.encodeToString(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        expertInfoVo.setExpertPhotoSrc(base64Str);
        return expertInfoVo;
    }

    /**
     * 删除专家信息
     *
     * @param ids
     */
    @Override
    @Transactional
    public void deleteExpert(List<Long> ids) {
        ids.forEach(id->{
            List<Long> projectList = this.extractResultService.lambdaQuery()
                    .eq(ExtractResult::getExpertId, id)
                    .eq(ExtractResult::getObsolete,0)
                    .list()
                    .stream().map(ExtractResult::getProjectId).toList();
            Long count =0L;
            if (projectList.size()>0){
                count = this.projectService.lambdaQuery()
                        .between(Project::getProjectStatus, ProjectStatus.DRAWN.getCode(),ProjectStatus.NOT_REVIEW)
                        .in(Project::getId,projectList)
                        .count();
            }
            if (count>0){
                Expert expert = this.getById(id);
                throw  new DeleteException(expert.getExpertName()+"存在有未完成事项，删除失败");
            }
        });
        List<Expert> expertList = this.lambdaQuery().in(Expert::getId, ids).list();
        List<Long> userIds = expertList.stream().map(Expert::getExpertUser).toList();
        //删除通知
        this.noticeUserService.remove(new LambdaQueryWrapper<NoticeUser>().in(userIds.size()>0,NoticeUser::getUserId,ids));
        this.removeBatchByIds(ids);
        this.userService.removeBatchByIds(userIds);
    }

    /**
     * 修改专家信息
     *
     * @param expert
     */
    @Override
    @Transactional
    public void updateExpertService(Expert expert) {
        //查询身份证信息是否已经存在
        Long count = this.lambdaQuery().ne(Expert::getId, expert.getId()).eq(Expert::getExpertIdNumber, expert.getExpertIdNumber()).count();
        if (count>0){
            throw new UpdateException(MessageConstant.EXPERT_ID_NUMBER_REPEAT);
        }

        Expert dbExpert = this.lambdaQuery().eq(Expert::getId, expert.getId()).one();
        if (dbExpert!=null){
            //删除旧的图片
            String expertPhoto = dbExpert.getExpertPhoto();
            System.out.println(expertPhoto);

            String oldPhotoPath=this.localPhotoPath+expertPhoto;
            if (expert.getExpertPhoto()!=null&&!expertPhoto.equals(expert.getExpertPhoto())) {
                File file = new File(oldPhotoPath);
                if (file.exists() && file.isFile()) {
                    file.delete();
                }
            }
            //修改信息
            BeanUtils.copyProperties(expert,dbExpert);
            dbExpert.setUpdateTime(LocalDateTime.now());
            dbExpert.setUpdateUser(BaseContext.getCurrentId());
            this.update(dbExpert,new LambdaQueryWrapper<Expert>().eq(Expert::getId,dbExpert.getId()));
        }else{
            throw  new UpdateException(MessageConstant.EXPERT_NOT_FOUND);
        }
    }

    @Override
    public List<RemoteExpertVo> selectByName(String name) {
        List<Expert> expertList = this.lambdaQuery().like(Expert::getExpertName, name).list();
        return expertList.stream().map(expert -> {
            RemoteExpertVo remoteExpertVo=new RemoteExpertVo();
            BeanUtils.copyProperties(expert,remoteExpertVo);
            remoteExpertVo.setName(expert.getExpertName());
            String idNumber = expert.getExpertIdNumber();
            remoteExpertVo.setIdNumber(idNumber.substring(idNumber.length()-6));
            return remoteExpertVo;
        }).collect(Collectors.toList());
    }
}
